package __linnear_list

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

/**
顺序表的链式结构
单链表
*/

type node struct {
	data int
	next *node
}

func NewLinkList() *node {
	// 返回头节点
	// 头结点的数据作为整个顺序表的长度
	return &node{}
}

// AddElement 在列表尾部添加元素
// 如果列表已满 -> -1
// 成功        -> 下标值
func (l *node) AddElement(e int) int {
	index := -1
	t := l // 起始位置是头结点
	for i := 0; i < l.data; i++ {
		t = t.next
	}
	// 遍历到最后一个
	if t.next == nil {
		n := &node{data: e, next: nil}
		t.next = n
		l.data++
	}
	index = l.data - 1
	return index
}

// InsertElement 在 i 位置插入元素
// 如果 i 不符合规则 -> -1
// 成功 -> 0
func (l *node) InsertElement(e, i int) int {
	if !l.indexLegal(i) {
		return -1
	}
	// 遍历都是从头结点开始
	t := l
	for j := 0; j < l.data; j++ {
		if j == i {
			n := &node{data: e, next: t.next}
			t.next = n
		}
		t = t.next
	}
	l.data++
	return 0
}

// DeleteElement 删除第一个匹配的元素
// 成功 -> 下标值
// 失败 -> -1
func (l *node) DeleteElement(e int) int {
	r := -1
	t := l
	for i := 0; i < l.data; i++ {
		if t.next.data == e {
			r = i
			break
		}
		t = t.next
	}
	if r != -1 {
		t.next = t.next.next
		l.data--
	}
	return r
}

// DeleteIndex 删除下标为 i 的值
// 成功 -> 值
// index 不符合规则 -> error
func (l *node) DeleteIndex(i int) (int, error) {
	if !l.indexLegal(i) {
		return -1, errors.New("delete index error: i out of range")
	}
	r := -1
	t := l
	for j := 0; j < l.data; j++ {
		if j == i {
			r = t.next.data
			t.next = t.next.next
			l.data--
			break
		}
		t = t.next
	}
	return r, nil
}

// Update 将下标为 i 的值修改为 e
// 成功 -> 0
// i 不符合规则 -> -1
func (l *node) Update(e, i int) int {
	if !l.indexLegal(i) {
		return -1
	}
	r := -1
	t := l
	for j := 0; j < l.data; j++ {
		if j == i {
			t.next.data = e
			r = 0
			break
		}
		t = t.next
	}
	return r
}

// GetElement 返回下标为 i 的值
// 成功 -> 值
// i 不符合规则 -> error
func (l *node) GetElement(i int) (int, error) {
	if !l.indexLegal(i) {
		return -1, errors.New("get element error: i out of range")
	}
	t := l
	for j := 0; j < l.data; j++ {
		if j == i {
			return t.next.data, nil
		}
		t = t.next
	}
	return -1, errors.New("get element error")
}

// LocateElement 查找第一个与 e 相等的元素
// 成功 -> 下标
// 失败 -> -1
func (l *node) LocateElement(e int) int {
	r := -1
	t := l
	for j := 0; j < l.data; j++ {
		if t.next.data == e {
			r = j
		}
		t = t.next
	}
	return r
}

func (l *node) IsEmpty() bool {
	return l.data == 0
}

func (l *node) Clear() {
	l.data = 0
}

func (l *node) indexLegal(i int) bool {
	return i >= 0 && i < l.data
}

func (l *node) String() string {
	t := l.next
	sb := strings.Builder{}
	for i := 0; i < l.data; i++ {
		sb.WriteString(strconv.Itoa(t.data))
		if i != l.data-1 {
			sb.WriteString("->")
		}
		t = t.next
	}
	return fmt.Sprintf("length=%d, data=%s", l.data, sb.String())
}
